package cn.lisens.valid.web;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Map;
import java.util.stream.Collectors;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

@RestControllerAdvice
public class GlobalExceptionHandler {
	
	private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	/**
     * 全局拦截 @RequestBody的DTO的Json数据校验
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {
    	System.err.println("MethodArgumentNotValidException捕获");
    	Map<String, String> errors = ex.getBindingResult().getFieldErrors()
                .stream()
                .collect(Collectors.toMap(
                    FieldError::getField,
                    fieldError -> fieldError.getDefaultMessage() != null 
                        ? fieldError.getDefaultMessage() 
                        : "Invalid value"
                ));
        
        return ResponseEntity.badRequest()
                .body(new ErrorResponse("VALIDATION_FAILED", "参数校验失败", errors));
    }
    
    /**
     * 全局拦截 Controller类被@Validate修饰后，在方法的参数前面直接修饰校验规则
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<ErrorResponse> handleConstraintViolation(
            ConstraintViolationException ex) {
        
        // 提取详细的错误信息
        Map<String, String> errors = ex.getConstraintViolations()
            .stream()
            .collect(Collectors.toMap(
                violation -> violation.getPropertyPath().toString(),
                ConstraintViolation::getMessage
            ));
        
        logger.warn("ConstraintViolationException参数校验失败: {}", errors);
        
        return ResponseEntity.badRequest()
                .body(new ErrorResponse("VALIDATION_FAILED","参数校验不通过",errors));
    }
    
    /**
     * 全局拦截通过url的query参数或者form-data提交的数据校验
     * @param ex
     * @return
     */
    @ExceptionHandler(BindException.class)
    public ResponseEntity<ErrorResponse> handleBindException(BindException ex) {
    	Map<String, String> errors = ex.getBindingResult().getFieldErrors()
    		    .stream()
    		    .collect(Collectors.toMap(
    		        FieldError::getField,
    		        fieldError -> fieldError.getDefaultMessage() != null ? fieldError.getDefaultMessage() : "Invalid value",
    		        (existingMessage, newMessage) -> existingMessage + "; " + newMessage // 合并策略
    		    ));
        return ResponseEntity.badRequest()
                .body(new ErrorResponse("VALIDATION_FAILED", "参数绑定失败", errors));
        
    }
    

    @Data
    @AllArgsConstructor
    private static class ErrorResponse {
        private String code;
        private String message;
        private Map<String, String> errors;
    }
}
